#pragma once

#include "DBXDevice.h"

#include <string>

namespace libconfig { class Setting; }
namespace DBX
{
    using namespace libconfig;
    class DBXDeviceFactory;
    class TKSPRODLLEXPORT DBXDeviceManager
    {
        DBXDeviceManager(DBXDeviceManager const &) = default;
        DBXDeviceManager(DBXDeviceManager &&) = default;
        DBXDeviceManager &operator=(DBXDeviceManager const &) = default;
        DBXDeviceManager &operator=(DBXDeviceManager &&) = default;

    public:
        DBXDeviceManager(void);
        ~DBXDeviceManager(void);

        static DBXDeviceManager *instance();

        int deviceCount() const;
        DBXDevice::Ptr deviceAt(int index) const;
        DBXDevice::Ptr find(const std::string &devName) const;
        bool hasDevice(const std::string &devName) const;
        void addDevice(const DBXDevice::Ptr &device);
        void removeDevice(const std::string &devName);
        void setDeviceConnected(const std::string &devName, bool connected);

        void init();
        void destroy();
        void reConnect(const std::string &devName);

        void attachConnectionMonitor(void *pObj, void(*pHandle)(void *, std::string, bool) = nullptr);
        void attachDestroyMonitor(void *pObj, void(*pHandle)(void *) = nullptr);
        void attachLogMessageMonitor(void *pObj, void(*pHandler)(void *, const std::string &, time_t, int) = nullptr);

    private:
        void save();
        void load();
        static const DBXDeviceFactory *restoreFactory(const Setting &setting);
        void fromSetting(const Setting &setting);
        void toSetting(Setting &settins) const;

        static std::string settingsFilePath(const std::string &extension);

    private:
        class Private;
        Private &p;
    };
} // namespace DBX